package com.bootdo.common.controller;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.hutool.core.convert.Convert;
import com.bootdo.common.domain.GenTableColumnDO;
import com.bootdo.common.service.GenTableColumnService;
import com.bootdo.common.utils.*;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Workbook;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bootdo.common.domain.GenTableDO;
import com.bootdo.common.service.GenTableService;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * 代码生成业务表
 *
 * @author rhgs
 * @email rhgs@163.com
 * @date 2024-01-22 14:44:59
 */

@Controller
@RequestMapping("/common/genTable")
public class GenTableController {
    @Autowired
    private GenTableService genTableService;

    @Autowired
    private GenTableColumnService genTableColumnService;


    @GetMapping("/genCode/{tableName}")
    public void genCode(HttpServletResponse response,
                        @PathVariable("tableName") String tableName) throws IOException {
        // 1. 生成代码ZIP数据
        byte[] data = genTableService.generatorCode(tableName);

        // 2. 获取项目根目录（假设是标准Spring Boot项目结构）
        String projectRoot = System.getProperty("user.dir");
        String projectRoot1 = "D:\\dn\\Desktop\\svn_code\\pro\\official_platform";
//        String outputDir = projectRoot + "/src/";
//        System.out.println(outputDir);

        // 3. 在服务器端解压到项目src目录（后台执行）
        new Thread(() -> {
            try {
                extractZipToProject(data, projectRoot);
//                extractZipToProject(data, projectRoot1);
                System.out.println("代码已解压到项目src目录: " + projectRoot);
            } catch (IOException e) {
                System.err.println("解压失败: " + e.getMessage());
            }
        }).start();

        // 4. 返回ZIP文件给浏览器下载
        genCode(response, data);
    }

    /**
     * 安全解压到项目目录
     */
    private void extractZipToProject(byte[] zipData, String projectDir) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipData))) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                // 跳过MACOS的隐藏文件
                if (entry.getName().contains("__MACOSX") || entry.getName().startsWith(".")) {
                    continue;
                }

                File entryFile = new File(projectDir, entry.getName());

                // 安全校验：确保解压路径在项目目录内
                String canonicalDestPath = entryFile.getCanonicalPath();
                String canonicalProjectPath = new File(projectDir).getCanonicalPath();

                if (!canonicalDestPath.startsWith(canonicalProjectPath)) {
                    throw new IOException("禁止解压到项目目录外: " + entry.getName());
                }

                if (entry.isDirectory()) {
                    if (!entryFile.exists() && !entryFile.mkdirs()) {
                        throw new IOException("无法创建目录: " + entryFile.getAbsolutePath());
                    }
                } else {
                    // 确保父目录存在
                    File parent = entryFile.getParentFile();
                    if (parent != null && !parent.exists() && !parent.mkdirs()) {
                        throw new IOException("无法创建父目录: " + parent.getAbsolutePath());
                    }

                    // 写入文件
                    try (FileOutputStream fos = new FileOutputStream(entryFile)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                }
                zis.closeEntry();
            }
        }
    }

    /**
     * 返回ZIP文件下载（原方法不变）
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.setHeader("Content-Disposition", "attachment; filename=\"bootdo.zip");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }


    /**
     * 查询数据表字段列表
     */
    @GetMapping("/column/list")
    @ResponseBody
    public PageUtils columnList(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<GenTableColumnDO> genTableList = genTableColumnService.selectGenTableColumnListByTableId(query);
        int total = genTableColumnService.countSelectGenTableColumnListByTableId(query);
        PageUtils pageUtils = new PageUtils(genTableList, total);
        return pageUtils;
    }

    /**
     * 查询数据库列表
     */
    @RequiresPermissions("common:genTable:genTable")
    @GetMapping("/db/list")
    @ResponseBody
    public PageUtils dataList(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<GenTableDO> genTableList = genTableService.selectDbTableList(query);
        int total = genTableService.countSelectDbTableList(query);
        PageUtils pageUtils = new PageUtils(genTableList, total);
        return pageUtils;
    }


    /**
     * 导入表结构
     */
    @RequiresPermissions("common:genTable:genTable")
    @GetMapping("/importTable")
    public String importTable() {
        return "/common/genTable/importTable";
    }


    /**
     * 导入表结构（保存）
     */
    @ResponseBody
    @PostMapping("/importTable")
    @RequiresPermissions("common:genTable:add")
    public R importTable(String tables) {
        String[] tableNames = Convert.toStrArray(tables);
        List<GenTableDO> tableList = genTableService.selectDbTableListByNames(tableNames);
        genTableService.importGenTable(tableList);
//        genTable.setUuid(idWorker.nextId() + "");
//        if (genTableService.save(genTable) > 0) {
//            return R.ok();
//        }
        return R.error();
    }

    @RequestMapping("/exportColumn")
    @ResponseBody
    @RequiresPermissions("common:genTable:add")
    void exportColumn(String type, HttpServletResponse response, @RequestParam Map<String, Object> params) throws Exception {
        List<GenTableDO> genTableDOS = genTableService.list(params);
        String title = "代码生成业务表" + DateUtils.format(new Date());
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(title, null),
                GenTableDO.class, genTableDOS);
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(title, "utf-8") + ".xls");
        workbook.write(response.getOutputStream());
        workbook.close();
    }

    @GetMapping()
    @RequiresPermissions("common:genTable:genTable")
    String GenTable() {
        return "common/genTable/genTable";
    }

    @ResponseBody
    @GetMapping("/list")
    @RequiresPermissions("common:genTable:genTable")
    public PageUtils list(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<GenTableDO> genTableList = genTableService.list(query);
        int total = genTableService.count(query);
        PageUtils pageUtils = new PageUtils(genTableList, total);
        return pageUtils;
    }

    @GetMapping("/add")
    @RequiresPermissions("common:genTable:add")
    String add() {
        return "common/genTable/add";
    }

    @GetMapping("/edit/{tableId}")
    @RequiresPermissions("common:genTable:edit")
    String edit(@PathVariable("tableId") Long tableId, Model model) {
        GenTableDO genTable = genTableService.get(tableId);
        model.addAttribute("genTable", genTable);
        return "common/genTable/edit";
    }

    /**
     * 保存
     */
    @ResponseBody
    @PostMapping("/save")
    @RequiresPermissions("common:genTable:add")
    public R save(GenTableDO genTable) {
        IdWorker idWorker = new IdWorker();
//        genTable.setUuid(idWorker.nextId() + "");
        if (genTableService.save(genTable) > 0) {
            return R.ok();
        }
        return R.error();
    }

    /**
     * 修改
     */
    @ResponseBody
    @RequestMapping("/update")
    @RequiresPermissions("common:genTable:edit")
    public R update(GenTableDO genTable) {
        genTableService.update(genTable);
        return R.ok();
    }

    /**
     * 删除
     */
    @PostMapping("/remove")
    @ResponseBody
    @RequiresPermissions("common:genTable:remove")
    public R remove(Long tableId) {
        if (genTableService.remove(tableId) > 0) {
            return R.ok();
        }
        return R.error();
    }

    /**
     * 删除
     */
    @PostMapping("/batchRemove")
    @ResponseBody
    @RequiresPermissions("common:genTable:batchRemove")
    public R remove(@RequestParam("ids[]") Long[] tableIds) {
        genTableService.batchRemove(tableIds);
        return R.ok();
    }

}
